
package lumis.service.wsrp.consumer.producermanager;

import lumis.portal.PortalException;
import lumis.portal.dao.DaoException;
import lumis.portal.manager.ManagerFactory;
import lumis.portal.transaction.ITransaction;
import lumis.portal.transaction.PortalTransactionFactory;

import java.net.URL;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.persistence.EntityManager;

import com.sun.portal.wsrp.common.WSRPVersion;
import com.sun.portal.wsrp.common.stubs.v2.Lifetime;
import com.sun.portal.wsrp.common.stubs.v2.RegistrationContext;
import com.sun.portal.wsrp.common.stubs.v2.RegistrationData;
import com.sun.portal.wsrp.common.stubs.v2.ServiceDescription;
import com.sun.portal.wsrp.common.stubs.v2.SetRegistrationLifetime;
import com.sun.portal.wsrp.consumer.common.WSRPConsumerException;
import com.sun.portal.wsrp.consumer.producermanager.PortTypeImplFactory;
import com.sun.portal.wsrp.consumer.producermanager.ProducerEntity;
import com.sun.portal.wsrp.consumer.producermanager.ProducerEntityStatus;
import com.sun.portal.wsrp.consumer.producermanager.impl.AbstractProducerEntityManager;

/**
 * Lumis implementation of the ProducerEntityManager interface. Responsible for
 * managing the consumer's ProducerEntity and track the configurations of the
 * remote portlet/service.
 * 
 * @version $Revision: 13048 $ $Date: 2011-05-25 10:19:48 -0300 (Wed, 25 May 2011) $
 * @since 5.5.0
 */
@SuppressWarnings("unchecked")
public class ProducerEntityManagerImpl extends AbstractProducerEntityManager
{
	private String serviceInstanceId;
	private RegistrationData defaultRegistrationData;

	public ProducerEntity getProducerEntity(String producerEntityId) throws WSRPConsumerException
	{
		try
		{
			ITransaction transaction = PortalTransactionFactory.createTransaction();
			try
			{
				transaction.begin();
				ProducerEntityImpl producer = ManagerFactory.getEntityManager().find(ProducerEntityImpl.class, producerEntityId);
				transaction.commit();
				return producer;
			}
			finally
			{
				transaction.dispose();
			}
		}
		catch (DaoException e)
		{
			throw new WSRPConsumerException(e.getMessage(), e);
		}

	}

	public Set<String> getProducerEntityIds() throws WSRPConsumerException
	{
		try
		{
			ITransaction transaction = PortalTransactionFactory.createTransaction();
			try
			{
				transaction.begin();
				List<String> producerEntityIds = (List<String>) ManagerFactory.getEntityManager().createNamedQuery(
						ProducerEntityImpl.NAMED_QUERY_FIND_PRODUCER_ENTITY_ID_BY_PRODUCER_NAME)
						.setParameter("producerName", serviceInstanceId)
						.getResultList();
				transaction.commit();
				
				return new HashSet<String>(producerEntityIds);
			}
			finally
			{
				transaction.dispose();
			}
		}
		catch (DaoException e)
		{
			throw new WSRPConsumerException(e.getMessage(), e);
		}
	}

	public void init(String portalId, String serviceInstanceId) throws WSRPConsumerException
	{
		this.serviceInstanceId = serviceInstanceId;
	}

	public boolean isActivated() throws WSRPConsumerException
	{
		return true;
	}

	/**
	 * Currently unsupported
	 */
	public void setActivated(boolean active) throws WSRPConsumerException
	{
		// ignore
	}

	/**
	 * Currently no identity propagation is not allowed. See
	 * {@link lumis.service.wsrp.consumer.producermanager.ProducerEntityImpl#setIdentityPropagationType(String)}
	 */
	public void setIdentityPropagationType(String producerEntityId, String type) throws WSRPConsumerException
	{
		// ignore
	}

	public void setName(String producerEntityId, String name) throws WSRPConsumerException
	{
		try
		{
			ITransaction transaction = PortalTransactionFactory.createTransaction();
			try
			{
				transaction.begin();

				EntityManager manager = ManagerFactory.getEntityManager();
				ProducerEntityImpl producer = manager.find(ProducerEntityImpl.class, producerEntityId);
				producer.setName(name);

				transaction.commit();
			}
			finally
			{
				transaction.dispose();
			}
		}
		catch (DaoException e)
		{
			throw new WSRPConsumerException(e.getMessage(), e);
		}
	}

	public void setStatus(String producerEntityId, ProducerEntityStatus status) throws WSRPConsumerException
	{
		try
		{
			ITransaction transaction = PortalTransactionFactory.createTransaction();
			try
			{
				transaction.begin();

				EntityManager manager = ManagerFactory.getEntityManager();
				ProducerEntityImpl producer = manager.find(ProducerEntityImpl.class, producerEntityId);
				producer.setStatus(status);

				transaction.commit();
			}
			finally
			{
				transaction.dispose();
			}
		}
		catch (DaoException e)
		{
			throw new WSRPConsumerException(e.getMessage(), e);
		}
	}

	public void purgeProducerEntity(String producerEntityId) throws WSRPConsumerException
	{
		EntityManager manager = ManagerFactory.getEntityManager();
		ProducerEntityImpl producerEntity = manager.find(ProducerEntityImpl.class, producerEntityId);
		if (producerEntity.getRegistration() != null)
		{
			Registration registration = manager.find(Registration.class, producerEntity
					.getRegistration().getRegistrationHandle());

			if (registration != null)
			{
				manager.remove(registration);
			}
		}
		manager.remove(producerEntity);
	}

	/**
	 * Registration is currently not supported.
	 */
	public void storeModifiedRegistration(String producerEntityId, String rdXML, String rcXML) throws WSRPConsumerException
	{
		// ignore
	}

	public void storeProducerEntity(ProducerEntity pe) throws WSRPConsumerException
	{
		try
		{
			ITransaction transaction = PortalTransactionFactory.createTransaction();
			try
			{
				transaction.begin();
				
				EntityManager manager = ManagerFactory.getEntityManager();
				ProducerEntityImpl producerEntityImpl = (ProducerEntityImpl)pe;
				Registration registration = producerEntityImpl.getRegistration();		
				manager.persist(pe);
				if(registration != null)
				{
					Registration find = manager.find(registration.getClass(), registration.getRegistrationHandle());
					if(find == null)
						manager.persist(registration);
					else
						throw new WSRPConsumerException("STR_WSRP_REGISTRATION_EXISTS"); 
					
				}
				
				transaction.commit();
			}
			finally
			{
				transaction.dispose();
			}
		}
		catch (DaoException e)
		{
			throw new WSRPConsumerException(e.getMessage(), e);
		}
	}

	public void storeUpdatedServiceDescription(String producerEntityId, String sdXML) throws WSRPConsumerException
	{
		try
		{
			ITransaction transaction = PortalTransactionFactory.createTransaction();
			try
			{
				transaction.begin();

				EntityManager manager = ManagerFactory.getEntityManager();
				ProducerEntityImpl producer = manager.find(ProducerEntityImpl.class, producerEntityId);
				producer.setServiceDescription(sdXML);

				transaction.commit();
			}
			finally
			{
				transaction.dispose();
			}
		}
		catch (DaoException e)
		{
			throw new WSRPConsumerException(e.getMessage(), e);
		}
	}

	/**
	 * Creates a new instance of ProducerEntity and return it
	 */
	@Override
	protected ProducerEntity createProducerEntity(
								String producerEntityId,
								String producerName,
								URL producerURL,
								String markupEndpoint,
								ProducerEntityStatus status,
								RegistrationData regData,
								RegistrationContext regContext,
								ServiceDescription serviceDesc,
								Map userCategories,
								Map allowedUserProfiles,
								Map customUserProfiles,
								long serviceDescLastModified,
								String lastModified,
								int entityVersion,
								String identityPropagationType,
								String producerVersion,
								Lifetime lifetime)
						throws WSRPConsumerException
	{
		String sdXML = getServiceDescriptionXMLFromSD(serviceDesc);
		return new ProducerEntityImpl(regContext, null, producerName, producerURL, WSRPVersion.fromValue(producerVersion), markupEndpoint, status, sdXML, serviceDescLastModified);
	}

	// -- Not Yet Supported -- //

	/**
	 * Currently unsupported
	 * 
	 * @return null
	 */
	public Map<String, String> getStandardUserProfileMapping() throws WSRPConsumerException
	{
		// not yet supported
		return null;
	}

	/**
	 * Currently unsupported
	 */
	public void setAllowedUserProfileMapping(String producerEntityId, Map<String, String> allowedUserProfileMap) throws WSRPConsumerException
	{
		// not yet supported
	}

	/**
	 * Currently unsupported
	 */
	public void setCustomUserProfileMapping(String producerEntityId, Map<String, String> customUserProfileMap) throws WSRPConsumerException
	{
		// not yet supported
	}

	/**
	 * Currently unsupported
	 */
	public void setDefaultRegistrationData(RegistrationData rd) throws WSRPConsumerException
	{
		this.defaultRegistrationData = rd;
	}

	/**
	 * Currently unsupported
	 */
	public void setUserCategoryMapping(String producerEntityId, Map<String, String> userCategoryMap) throws WSRPConsumerException
	{
		// not yet supported
	}

	/**
	 * Currently unsupported
	 */
	public void setStandardUserProfileMapping(Map<String, String> standardUserProfileMap) throws WSRPConsumerException
	{
		// not yet supported
	}

	/**
	 * Currently unsupported
	 * 
	 * @return null
	 */
	public RegistrationData getDefaultRegistrationData() throws WSRPConsumerException
	{
		try
		{
			if (defaultRegistrationData == null)
			{
				defaultRegistrationData = DefaultRegistrationDataBuilder
											.initDefaultRegistrationData(serviceInstanceId);
			}
			return defaultRegistrationData;			
		}
		catch (PortalException pe)
		{
			throw new WSRPConsumerException("Error trying to build the default Registration Data.", pe);
		}
	}

	/**
	 * Currently unsupported
	 */
	public String getConsumerName() throws WSRPConsumerException
	{
		throw new UnsupportedOperationException("getConsumerName is unsupported in the current version.");
	}

	/**
	 * Currently unsupported
	 */
	public void setConsumerName(String consumerName) throws WSRPConsumerException
	{
		// ignore. See getConsumerName
	}
	
	/**
	 * Call the setRegistrationLifetime method that allows a consumer to request a change to the lifetime.
	 * @param producerEntityId
	 * @param lifetime
	 * @throws WSRPConsumerException
	 */
	public void setLifetime(ProducerEntity producerEntity, Lifetime lifetime) throws WSRPConsumerException
	{
		// ProducerEntity producerEntity = getProducerEntity(producerEntityId);
		URL url = producerEntity.getURL();
		
		SetRegistrationLifetime methodSetRegistrationLifetime = new SetRegistrationLifetime();
		methodSetRegistrationLifetime.setRegistrationContext(producerEntity.getRegistrationContext());
		methodSetRegistrationLifetime.setLifetime(lifetime);
				
		WSRPVersion version = producerEntity.getVersion();
		try
		{
			PortTypeImplFactory.getPortTypeImpl(version.value()).setRegistrationLifetime(url, methodSetRegistrationLifetime);
		}
		catch (Exception e)
		{
			throw new WSRPConsumerException(e.getMessage(), e);
		}
	}	
}